package game;

import java.awt.Point;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * The Knight's Tour is a unique game where one <tt>Knight</tt> begins at the centre of the board and moves 
 * around the board touching each square only once. Once all the squares have been touched only
 * once the game is complete.
 * 
 * @author Nicole Waldrum
 * @date January 30, 2010
 * @version 1.0
 * 
 * @author Mark Kelly
 * @date February 20, 2010
 * @version 2.0
 *
 */
public class KnightTour extends GameType {
	// InstanceVariables
    private Set<Point> usedSquares;
    
    /**
	 * Creates a new instance of <tt>KnightTour</tt>.
	 * 
	 * After this constructor returns, setGameState() must be called before any other method is invoked.
	 */
	public KnightTour() {
		super();
		usedSquares = new HashSet<Point>();
	}

	/**
	 * {@inheritDoc}
	 * 
	 * In the case of the Knight's tour, the new position of the <tt>Knight</tt> is added to the 'blacklist' of spaces that the <tt>Knight</tt> has used.
	 */
	public void pieceMoved (Piece p) {
		usedSquares.add(p.getLocation());
	}

	/**
	 * {@inheritDoc}
	 * 
	 * In the case of the Knight's Tour, a single <tt>Knight</tt> is placed on the board.
	 */
	@Override
	public void setupBoard() {
		ChessBoard board = new ChessBoard(boardSize);
		
		Point start = new Point (1, 1);
		
		board.addPiece(new Knight(start, Team.BLACK));
		
		usedSquares.add(start);
		
		state.setBoard(board);
	}
	
	/**
	 * {@inheritDoc}
	 * 
	 * In the case of the Knight's Tour, each square must have been visited once.
	 */
	@Override
	public boolean hasWon(Team team) {
		return (usedSquares.size() == 64);
	}
	
	/**
	 * {@inheritDoc}
	 * 
	 * In the case of the Knight's Tour, the square cannot have been previously visited by the <tt>Knight</tt>.
	 */
	public boolean isValidMove(Piece piece, Point dest){
		return !(usedSquares.contains(dest));
	}

	@Override
	public boolean movePiece(Point start, Point dest) {
		ChessBoard board = state.getBoard();
		if (board.hasPieceAt(start)) {
			Piece p = board.getPieceAt(start);
			// check if its a valid move and if the pawn exception is in effect
			if (state.isValidMove(p, dest)) {
				board.movePiece(p, dest);
				state.pieceMoved(p);
				return true;
			}
		}
		// invalid move
		return false;
	}
}
